March 22, 2005
2と3をひたすら繰り返す.
重犯罪人に自分の罪を思い知らせるなら、土を掘り移動させ、それからまた埋めて元に戻す、という作業を延々と繰り返させればよい。それは究極の拷問であり、最後には精神に異常をきたすであろう。(ドフトエフスキー?)
プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムだよ.
ディレクトリを好きな時点の状態に復元できるよ.
よくない.
Google driveでできなくいことの例
Gitには3つの視点がある
これらを理解すればGit master.
Commit (directoryのスナップショット)からなるツリー.

1つのCommitの裏には3つのレイヤがある

fileには4つの状態がある

あなたは,gitマスターになりました.
異世界に行ったら最初に唱える呪文.
File statusが4つのどの状態にあるかの確認.
# 準備 cd path/to/workspace mkdir repo000 cd repo000
git status
これから何かする度になるべくgit statusしましょう.

カレントディレクトリをgit repositoryにする
git init
カレントディレクトリからgit direcoryを削除する
rm -R .git
ファイルをStaged areaに追加する.
git add [path ...]
echo "ROW000" > file000 git add file000

git reset [--soft | --hard] [<commit>] [path ...]
git reset HEAD file000
stage(git add)されたすべてのファイルを対象にしたい場合
git reset HEAD
staged(git add)されたすべてのファイルのコピーをGit Directoryへ記録する
# 準備 git add file000
git commit [--amend] [-m <msg>]
git commit -m "Added file000."

Git Directoryから最後のCommitを削除する
# 準備 cp file000 file001 git add file001 git commit -m "Added file001."
git reset --soft HEAD^ # HEAD^ = 1つ前の親Commit
addもなかったことに
# 復習 git reset HEAD
commitとaddの2つをまとめてなかったことに
git reset HEAD^
$ git reflog
e170b24 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
953913d HEAD@{1}: commit: Added file001. <-- resetするまえのHEADの位置
...
git reset HEAD@{1} # HEAD@{1} = 1つ前にHEADの指していたcommit
| HEAD | インデックス | 作業ディレクトリ | 作業ディレクトリ保護の有無 | |
|---|---|---|---|---|
|
Commit Level |
||||
|
|
REF |
いいえ |
いいえ |
はい |
|
|
REF |
はい |
いいえ |
はい |
|
|
REF |
はい |
はい |
いいえ |
|
|
HEAD |
はい |
はい |
はい |
|
File Level |
||||
|
|
いいえ |
はい |
いいえ |
はい |
|
|
いいえ |
はい |
はい |
いいえ |
つまり?
git reset --hard するときは気をつけよう.
ファイルをStaged areaとGit directoryから削除する
(=untracked(gitの追跡対象外)にする)
git rm [--cached] [path ...]
cd path/to/workspace mkdir repo002 echo "ROW000" > file000 git add file000 git commit -m "Added file000."
# 復習 git add file000 # tracked(gitの追跡対象指定)にする
git rm --cached file000
一生untrackedにしておきたいfileやdirectoryは,.gitignoreというfileを作ってそこに書く.
.gitignoreしたdirectory内の一部のfileのみをtrackedにしたい場合は,.gitkeepに書いてignoreされないようにする.
.gitignore(.gitkeep)については,自分でググってね. (i.e., あまり興味ない)

ファイルをWorking Directory, Staged area, Git directoryのすべてから削除する.
# 準備 git add file000
rm file000 git add file000 # git rm --cached file000でも良い git commit -m "Removed file000."
上の2つをまとめてやる
# 準備 git reset --hard HEAD^ # HEAD^ = 1つ前の親Commit
git rm file000 git commit -m "Removed file000."
ファイルをWorking Directory, Staged area, Git directoryのすべてにおいてmoveまたはrenameする.
Note: mvとrenameは本質的に同じ
git mv <source> <destination>
# 準備 git reset --hard HEAD^
git mv file000 file001 git commit -m "Renamed file000 to file001."
最後のCommitを変更する
# 準備 cd path/to/workspace mkdir repo003 echo "ROW000" > file000 cp file000 file001 git add file000 git commit -m "Added file000."
ファイルをaddし忘れたときとか,コメントを修正したい時とかに便利
git add file001 git commit --amend -m "Added file000 and file001."
直前だけじゃなく,もっと前まで遡って自分の都合の良いように歴史を改変したい
git rebase -i <commit>
<commit>からHEADまでのコミットをまとめて変更する
# 準備 for f in file001 file002 file003 gomi; do cp file000 $f; done # file001, file002, file003, gomiができれば何でも良い git add file001 git commit -m "Added file001." git add file002 git commit -m "Added file002." git add file003 git commit -m "「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される" git add gomi git commit -m "Added gomi."
git rebase -i <commit>
* bf1b31a (HEAD -> master) Added gomi. # * fb7cc7b 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # <-- HEAD~1 or HEAD^ * 469a642 Added file002. # <-- HEAD~2 or HEAD^^ * f8c8773 Added file001. # <-- HEAD~3 or HEAD^^^ * 2312317 Added file000. # <-- HEAD~4 or HEAD^^^^
<commit>には変更の根本となるcommitを指定する.
git rebase -i HEAD~4 # HEAD~4 = 4つ前の親Commit
この場合変更対象はHEAD - HEAD~3
pick 17b9da7 Added file001. pick 98ee317 Added file002. pick 9a7d9db 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される pick 00805cf Added gomi. # Rebase e170b24..00805cf onto e170b24 (4 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
1番目と2番目はまとめたくて,3番目のメッセージを書き直したくて,4番目は消したい.
pick 17b9da7 Added file001. s 98ee317 Added file002. e 9a7d9db 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される d 00805cf Added gomi. # Rebase e170b24..00805cf onto e170b24 (4 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
# This is a combination of 2 commits. # This is the 1st commit message: Added file001. # This is the commit message #2: Added file002. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (2 commands done): # pick 5b6d77f Added file001. # squash 21c25a0 Added file002. # Next commands to do (2 remaining commands): # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # drop cf942f2 Added gomi. # You are currently rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file001 # new file: file002
# This is a combination of 2 commits. # This is the 1st commit message: Added file001 and file002. # This is the commit message #2: # Added file002. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (2 commands done): # pick 5b6d77f Added file001. # squash 21c25a0 Added file002. # Next commands to do (2 remaining commands): # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # drop cf942f2 Added gomi. # You are currently rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file001 # new file: file002
[detached HEAD 0136ee2] Added file001 and file002. Date: Sat Feb 16 22:50:41 2019 +0900 2 files changed, 2 insertions(+) create mode 100644 file001 create mode 100644 file002 Stopped at 2f734eb... 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される You can amend the commit now, with git commit --amend # <-- commitを編集したいのでまずは,こっち Once you are satisfied with your changes, run git rebase --continue
git logを見てみると<commit>で指定した根本から枝分かれしていることがわかる
$ git log --oneline --graph --all * 87449ac (HEAD) 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される * 2f98c92 Added file001 and file002. | * bf1b31a (master) Added gomi. | * fb7cc7b 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される | * 469a642 Added file002. | * f8c8773 Added file001. |/ * 2312317 Added file000.
git commit --amend
「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (3 commands done): # squash 21c25a0 Added file002. # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # Next command to do (1 remaining command): # drop cf942f2 Added gomi. # You are currently editing a commit while rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file003 #
Added file003. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Sat Feb 16 22:50:41 2019 +0900 # # interactive rebase in progress; onto e170b24 # Last commands done (3 commands done): # squash 21c25a0 Added file002. # edit 2f734eb 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される # Next command to do (1 remaining command): # drop cf942f2 Added gomi. # You are currently editing a commit while rebasing branch 'master' on 'e170b24'. # # Changes to be committed: # new file: file003 #
終わったらcontinue
git rebase --continue
rebaseの途中でやっぱりやめたくなった
git rebase --abort
rebaseしたあと,やっぱりなかったことにしたくなった
rebaseは既存のcommitをコピーを作っているだけなので,元のcommitも残っている(見えなくなっているだけ).
* 99d7024 (master) Added file003 * 2f98c92 Added file001 and file002. | * bf1b31a (HEAD) Added gomi. # <-- 元のHEAD | * fb7cc7b 再帰で検索して「もしかして:再帰」をクリックすると…。 | * 469a642 Added file002. | * f8c8773 Added file001. |/ * 2312317 Added file000.
見えないcommitをたどるにはreflog.
$ git reflog
a264b19 (HEAD -> master) HEAD@{0}: rebase -i (finish): returning to refs/heads/master
a264b19 (HEAD -> master) HEAD@{1}: commit (amend): Added file003.
ecc3571 HEAD@{2}: rebase -i (edit): 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される
9070db1 HEAD@{3}: rebase -i (squash): Added file001 and file002.
408797f HEAD@{4}: rebase -i (start): checkout HEAD~4
92b7c29 HEAD@{5}: commit: Added gomi. # <-- rebase前のHEADの位置
...
git reset --hard HEAD@{5} # HEAD@{5} = 5つ前にHEADの指していたcommit
$ git reflog
92b7c29 (HEAD -> master) HEAD@{0}: reset: moving to HEAD@{5} # <-- さっきのreset
a264b19 (HEAD -> master) HEAD@{1}: rebase -i (finish): returning to refs/heads/master
a264b19 (HEAD -> master) HEAD@{2}: commit (amend): Added file003.
ecc3571 HEAD@{3}: rebase -i (edit): 「もしかして:再帰」をクリックすると「もしかして:再帰」が表示される
9070db1 HEAD@{4}: rebase -i (squash): Added file001 and file002.
408797f HEAD@{5}: rebase -i (start): checkout HEAD~4
92b7c29 HEAD@{6}: commit: Added gomi.
...
git reset --hard HEAD@{1}
基本の呪文 Commit treeを表示する
git log --oneline --graph --all
defaultのgit logは見にくいので,いい感じで表示してくれるwrapperもある.
$ git-foresta --all | less -RSX
99d7024c 2019-02-19 10:31 ○ ameono (master) Added file003
2f98c925 2019-02-19 10:31 ● ameono Added file001 and file002.
bf1b31ad 2019-02-19 10:31 │ ○ ameono (HEAD) Added gomi.
fb7cc7b0 2019-02-19 10:31 │ ● ameono 再帰で検索して「もしかして:再帰」をクリックすると…。
469a6426 2019-02-19 10:31 │ ● ameono Added file002.
f8c8773e 2019-02-19 10:31 │ ● ameono Added file001.
├─┘
2312317f 2019-02-19 10:30 ■ ameono Added file000.
Commit (directoryのスナップショット)からなるツリー.

# 準備 cd path/to/workspace git init echo "ROW000" > file000 git add file000 git commit -m "Added file000."
git branch [-d|-D] <branch-name> [<start-point>]
git branch feature/update_file000 master
feature/branch000という名前のタグを作る(指す先はmasterの指しているところ)
git branch -d feature/update_file000
強制的に削除する場合
git branch -D feature/update_file000
$ git branch -d feature/update_file000 Deleted branch feature/update_file000 (was e170b24). # <-- ここのhashを覚えておく
git checkout e170b24 git checkout -b feature/update_file000
git checkout [-b] [<branch>|<commit>]
git checkout feature/update_file000
HEADの指す先をfeature/branch000へ変える
branchの作成とcheckoutをいっぺんにやる
git checkout -b feature/update_file000
git branch testing

git checkout testing

CLIで見てみる
$ git branch feature/update_file000
$ git log --graph --all
* commit e170b24890ca2685d9414b15f3862a28b16b3828 (HEAD -> master, feature/branch000)
Author: ameono <4m3on0@gmail.com>
Date: Sat Feb 16 21:28:33 2019 +0900
Added file000.
$ git checkout feature/update_file000
$ git log --graph --all
* commit e170b24890ca2685d9414b15f3862a28b16b3828 (HEAD -> feature/branch000, master)
Author: ameono <4m3on0@gmail.com>
Date: Sat Feb 16 21:28:33 2019 +0900
Added file000.
HEAD -> の指す先に注目.
echo "ROW001" >> file000 git add file000 git commit -m "Updated file000 (added the second row)."
masterと違うCommitを指していることを確認
git log --oneline --graph --all
git checkout master cat file000 # update_file000ブランチの変更が反映されていないことを確認 cp file000 file001 git add file001 git commit -m "Added file001."
分岐したことを確認
git log --oneline --graph --all
他のbranchの先端と今のbranchの先端を統合するcommitを作る
git merge [<branch>]
GithubでPull requestをmergeするときはこんな感じのことをしている.
git checkout feature/update_file000 git merge master
$ git log --oneline --graph --all * 0b45d32 (HEAD -> feature/update_file000) Merge branch 'master' into feature/update_file000 |\ | * 179a3bc (master) Added file001. * | cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
Merge commitができている.
git checkout master git merge --no-ff feature/update_file000
$ git log --oneline --graph --all * 500adbb (HEAD -> master) Merge branch 'feature/update_file000' |\ | * 0b45d32 (feature/update_file000) Merge branch 'master' into feature/update_file000 | |\ | |/ |/| * | 179a3bc Added file001. | * cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
Merge commitがまたできている.
$ git log --oneline --graph --all * 500adbb (HEAD -> master) Merge branch 'feature/update_file000' |\ | * 0b45d32 (feature/update_file000) Merge branch 'master' into feature/update_file000 | |\ | |/ |/| * | 179a3bc Added file001. # <-- Merge前のmaterの位置 | * cf7cb13 Updated file000 (added the second row). # <-- Merge前のfeature/update_file000の位置 |/ * e170b24 Added file000.
master tagとupdate_file000 tagをそれぞれMerge前の位置に戻せば良い.
(復習) HEAD^ = 1つ前の親Commit
親が2つ以上ある場合 HEAD^N (N=親の番号) のように指定できる.
$ git show --name-only HEAD^
commit 179a3bce92c28cb9a6ac1ef4d8ff4002c83d2f7d
Author: ameono <4m3on0@gmail.com>
Date: Sun Feb 17 00:57:33 2019 +0900
Added file001.
$ git show --name-only HEAD^2
commit 0b45d32e5332152a5a44400d6394344199f4f968 (feature/update_file000)
Merge: cf7cb13 179a3bc
Author: ameono <4m3on0@gmail.com>
Date: Sun Feb 17 14:51:11 2019 +0900
Merge branch 'master' into feature/update_file000
HEAD~2と似てるけど,全然意味が違う.
$ git show --name-only HEAD~2
commit e170b24890ca2685d9414b15f3862a28b16b3828
Author: ameono <4m3on0@gmail.com>
Date: Sat Feb 16 21:28:33 2019 +0900
Added file000.

HEAD~N = HEADのN個前の親Commit
HEAD^N = HEADの1個前の親CommitのN番目
ex) 1個前の親の2番めの親Commit = HEAD~1^2
masterのMergeをなかったことに
git reset --hard HEAD^
$ git log --oneline --graph --all * 0b45d32 (feature/update_file000) Merge branch 'master' into feature/update_file000 |\ | * 179a3bc (HEAD -> master) Added file001. * | cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
update_file000のMergeをなかったことに
git checkout feature/update_file000 git reset --hard HEAD^
$ git log --oneline --graph --all * 179a3bc (master) Added file001. | * cf7cb13 (HEAD -> feature/update_file000) Updated file000 (added the second row). |/ * e170b24 Added file000.
簡単ですね?
今までの話が理解できていれば,mergeをなかったことにしたのをなかったことにもできるはず.
(復習) git checkout feature/update_file000 git merge master git checkout master git merge --no-ff feature/update_file000 <-- --no-ffに注目
no-ff = No Fast Forward
なしにしてやってみる
git checkout feature/update_file000 git merge master git checkout master git merge feature/update_file000
$ git log --oneline --graph --all * e6de5fd (HEAD -> master, feature/update_file000) Merge branch 'master' into feature/update_file000 |\ | * 179a3bc Added file001. * | cf7cb13 Updated file000 (added the second row). |/ * e170b24 Added file000.
git rebase [<branch>]
git rebase --continue | --skip | --abort | --quit |
他のbranchの先端に今のbranchの根本から先端までのcommitをまとめて移植する
# 準備 git branch -f feature/update_file000 HEAD^2 git reset --hard HEAD^ git checkout feature/update_file000
git rebase master
$ git log --oneline --graph --all * a336ea3 (HEAD -> feature/update_file000) Added file001. * cf7cb13 (master) Updated file000 (added the second row). * e170b24 Added file000.
$ git rebase feature/update_file000 First, rewinding head to replay your work on top of it... Fast-forwarded master to feature/update_file000. $ git log --oneline --graph --all * a336ea3 (HEAD -> master, feature/update_file000) Added file001. * cf7cb13 Updated file000 (added the second row). * e170b24 Added file000.
まずはmasterを戻す.
$ git reset --hard HEAD^ * a336ea3 (feature/update_file000) Added file001. * cf7cb13 (HEAD -> master) Updated file000 (added the second row). * e170b24 Added file000.
次にupdate_file000を戻す
$ git reflog
a336ea3 (HEAD -> feature/update_file000) HEAD@{2}: checkout: moving from master to feature/update_file000
cf7cb13 (master) HEAD@{3}: reset: moving to HEAD^
a336ea3 (HEAD -> feature/update_file000) HEAD@{4}: rebase finished: returning to refs/heads/master
a336ea3 (HEAD -> feature/update_file000) HEAD@{5}: rebase: checkout feature/update_file000
cf7cb13 (master) HEAD@{6}: checkout: moving from feature/update_file000 to master
a336ea3 (HEAD -> feature/update_file000) HEAD@{7}: rebase finished: returning to refs/heads/feature/update_file000
a336ea3 (HEAD -> feature/update_file000) HEAD@{8}: rebase: Added file001.
cf7cb13 (master) HEAD@{9}: rebase: checkout master
179a3bc HEAD@{10}: checkout: moving from master to feature/update_file000 # <-- これ
$ git reset --hard HEAD@{10}
$ git log --oneline --graph --all
* 179a3bc (HEAD -> feature/update_file000) Added file001.
| * cf7cb13 (master) Updated file000 (added the second row).
|/
* e170b24 Added file000.
Mergeより戻すのが面倒(reflog使わないかん)ですね.
このことから,rebaseとmergeならmergeを使うべきという人もいます.
公式曰く,
公開リポジトリにプッシュしたコミットをリベースしてはいけない
この指針に従っている限り、すべてはうまく進みます。もしこれを守らなければ、あなたは嫌われ者となり、友人や家族からも軽蔑されることになるでしょう。(Pro Git)
git cherry-pick <commit>...
他のbranchの特定のcommitを今のbranchの先端に移植する
$ git log --oneline --graph --all * 179a3bc (HEAD -> feature/update_file000) Added file001. | * cf7cb13 (master) Updated file000 (added the second row). |/ * e170b24 Added file000.
$ git cherry-pick cf7cb13
$ git log --oneline --graph --all * 8a1eae4 (HEAD -> feature/update_file000) Updated file000 (added the second row). * 179a3bc Added file001. | * cf7cb13 (master) Updated file000 (added the second row). |/ * e170b24 Added file000.
masterのcommitがfeature/update_file000へcopyされた
rebaseはcherry-pickを複数まとめてやっているだけとも言える.
# 準備 git reset --hard HEAD^ echo "ROW002 <- update_file000" >> file000
$ git merge master Auto-merging file000 CONFLICT (content): Merge conflict in file000 Automatic merge failed; fix conflicts and then commit the result.
ROW000 <<<<<<< HEAD ROW002 <- update_file000 ======= ROW001 >>>>>>> master
git checkout [--theirs|--ours] <paths> を使うgit checkout --theirs file000
ROW000 <<<<<<< HEAD # = --ours ROW002 <- update_file000 ======= ROW001 >>>>>>> master # = --theris
merge元のbranch(=–theirs)の変更かmerge先(=HEAD, –ours)の変更かのどちらかを採用する.
欠点: どういう結果になるか予想がつきにくい.
merge-toolには色々ある.
git mergetool --tool=vimdiff
DiffがあるChunk(=色が変わっている部分)にカーソルを合わせ, 1do, 2do, 3doと入力することで,それぞれ上段の左から1番目,2番目,3番目が今後の姿に取り込まれる.
PyCharmのようにConflictを解消するツールが付いているIDEもある.

GitHub は世界最大の Remote Git リポジトリホスティングサービスだよ.
つまり?
localのrepository = localのPCにおいてあるdirecotry
とすると,
Github上のrepository = Google driveにおいてあるdirecotry
のような関係.
有名どころ
Github
Gitlab
Bitbucket
Githubがやたら有名だが他にもある (Google driveとDropbox的な関係).
できることは大差ないので,お財布事情とUIの好みの問題
(あとは狸と猫のどっちが好きかとか…バケツ…).

とにかく有名 (連携サービスが多いイメージ).
お金たくさん持ってく.
Github Educationとか言う学生プランに加入するとGithub含め色々な有名サービスが無料で使える.
本田圭佑がいる
他の2つと違い自前のCIとかはない(他のツールと組み合わせる前提OSSの思想的には○?)
どちらかというと,自組織のサーバにインストールして自分たちしかアクセスできないRemote repositoryとして使う (要するに自前のfile server的なやつ)オンプレミス版のほうが有名.
Slackを水で薄めたようなchatアプリやCIがついてくるので,これひとつで開発に必要なすべての作業を完結させることができる.
大人の事情でPublic臭の強いGithubとかSlackとかを使えない人たちが使ってるっぽい(NASAとか).
一昔前までPrivate repository(外部公開されない) 作り放題な唯一のサービスだったので,個人の利用者が多くいた(今は,Githubも作り放題).
Source treeの開発元でもあるAtlassianの製品.
お金ないらしい(最近値上げした).
https://stackshare.io/stackups/bitbucket-vs-github-vs-gitlab
2019 2月現在,各サービスの無料プランの状況
| Github | Bitbucket | Github (学生) | Bitbucket (学生) | GitLab | |
|---|---|---|---|---|---|
| private repository | 無制限 | 無制限 | 無制限 | 無制限 | 無制限 |
| public repository | 無制限 | 無制限 | 無制限 | 無制限 | 無制限 |
| collaborator | 3名まで | 5名まで | 無制限 | 無制限 | 無制限 |
| CI build time | - | 50分/月 | - | 500分/月 | 2000分/月 |
| LFS | 1GB | 1GB | 1GB | 5GB | 無制限? |
| LFS Bandwidth | 1GB/月 | 無制限 | 1GB/月 | 無制限 | 無制限? |
remote repositoryのcopyをlocalに作る.(= ダウンロード)
git clone <repository>
remote repository(のタグとcommit)を同期する
git pull [--rebase] <remote> <branch>
git fetch と git merge origin/master をまとめてやる(--rebaseつけるとgit rebase origin/masterになる)
git push <remote> <branch>
remoteの<branch>タグをlocalの<branch>タグの位置に同期させる(Conflictする場合はpushできない).
FYI: remote側で起こる動作は,<origin>/<branch>にcheckoutして
git merge --ff-only <branch>
したときに起こる動作と同じと考えることができる.
--ff-only勉強しといてよかったね!!!?